/*******************************************************************************
 FileName:      newMemPool.c
 Author:        urey
 Version :      1.0
 Date:          2015年7月9日
 Description:
 History:
 <author>		<time>			<version >      <desc>
 urey        2015年7月9日          1.0          create
 *******************************************************************************/

#include "memPool.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>

Uint32 gMemPoolCheck = 0;

MemPool_status initMemPool(MemPool** ppMemPool, apr_pool_t* pParent)
{
    if(ppMemPool == NULL)
    {
        return MEMPOOL_NULL_ERROR;
    }
    if(gMemPoolCheck == 0)
    {
        srand(clock());
        Uint8 temp[4] = {0};
        temp[0] = ((rand()%(16)) << 4) | (rand()%(16));
        temp[1] = ((rand()%(16)) << 4) | (rand()%(16));
        temp[2] = ((rand()%(16)) << 4) | (rand()%(16));
        temp[3] = ((rand()%(16)) << 4) | (rand()%(16));
        memcpy(&gMemPoolCheck, temp, sizeof(Uint32));
    }
    apr_initialize();
    apr_pool_t* pMyPool = NULL;
    if(APR_SUCCESS != apr_pool_create(&pMyPool, pParent))
    {
        return MEMPOOL_NULL_ERROR;
    }
    MemPool* pNewMemPool = apr_palloc(pMyPool, sizeof(MemPool));
    pNewMemPool->MemPoolHeader.pNextHead = &pNewMemPool->MemPoolHeader;
    pNewMemPool->MemPoolHeader.pPrevHead = &pNewMemPool->MemPoolHeader;
    *ppMemPool = pNewMemPool;
    return MEMPOOL_SUCCESS;
}

static MemPool_status newMemPoolNode(MemPoolNode** ppMemPoolNode, MemPoolHead* pMemPoolHead, Uint16 itemSize)
{
    if(ppMemPoolNode == NULL)
    {
        return MEMPOOL_NULL_ERROR;
    }
    Uint8* pNodeAndSpace = apr_palloc(pMemPoolHead->pApr_pool, itemSize + NODEHEADSIZE);
    if(pNodeAndSpace == NULL)
    {
        return MEMPOOL_NULL_ERROR;
    }
    memset(pNodeAndSpace, 0 ,itemSize + NODEHEADSIZE);
    MemPoolNode* pNewNode = (MemPoolNode*)pNodeAndSpace;
    pNewNode->pPrevNode = pNewNode;
    pNewNode->pNextNode = pNewNode;
    pNewNode->pMemPoolHead = pMemPoolHead;
    pNewNode->check = gMemPoolCheck;
    *ppMemPoolNode = pNewNode;
    return MEMPOOL_SUCCESS;
}

static MemPool_status newMemPoolHead(MemPoolHead** ppMemPoolHead, MemPool* pMemPool, Uint16 itemSize, Int32 itemNum)
{
    if (ppMemPoolHead == NULL)
    {
        return MEMPOOL_NULL_ERROR;
    }
    apr_pool_t* pMyPool = NULL;
    if(APR_SUCCESS != (apr_pool_create(&pMyPool, pMemPool->pApr_pool)))
    {
        return MEMPOOL_NULL_ERROR;
    }
    MemPoolHead* pNewMemPoolHead = apr_palloc(pMyPool, sizeof(MemPoolHead));
    if(pNewMemPoolHead == NULL)
    {
        return MEMPOOL_NULL_ERROR;
    }
    pNewMemPoolHead->pApr_pool = pMyPool;
    if(APR_SUCCESS!= apr_thread_mutex_create(&pNewMemPoolHead->pHeadMutex, APR_THREAD_MUTEX_DEFAULT, pMyPool))
    {
        apr_pool_destroy(pMyPool);
        return MEMPOOL_NULL_ERROR;
    }
    pNewMemPoolHead->pNextHead = pNewMemPoolHead;
    pNewMemPoolHead->pPrevHead = pNewMemPoolHead;
    pNewMemPoolHead->FreeMemHead.pNextNode = &pNewMemPoolHead->FreeMemHead;
    pNewMemPoolHead->FreeMemHead.pPrevNode = &pNewMemPoolHead->FreeMemHead;
    pNewMemPoolHead->UsedMemHead.pNextNode = &pNewMemPoolHead->UsedMemHead;
    pNewMemPoolHead->UsedMemHead.pPrevNode = &pNewMemPoolHead->UsedMemHead;
    pNewMemPoolHead->nodeSize = itemSize;
    pNewMemPoolHead->maxAvil = itemNum;
    /* 分配spaceNode */
    Int32 count = 0;
    Int32 errorFlag = 0;
    for(count = 0; count < itemNum; ++count)
    {
        MemPoolNode* pTempMemPoolNode = NULL;
        if(MEMPOOL_SUCCESS != newMemPoolNode(&pTempMemPoolNode, pNewMemPoolHead, itemSize))
        {
            errorFlag = 1;
            break;
        }
        /* 新创建的Node加入FreeHead */
        pTempMemPoolNode->pNextNode = pNewMemPoolHead->FreeMemHead.pNextNode;
        pTempMemPoolNode->pPrevNode = &pNewMemPoolHead->FreeMemHead;
        pNewMemPoolHead->FreeMemHead.pNextNode->pPrevNode = pTempMemPoolNode;
        pNewMemPoolHead->FreeMemHead.pNextNode = pTempMemPoolNode;
    }
    if(errorFlag)
    { /* 出错，删除NewMemPoolHead */
        apr_pool_destroy(pMyPool);
        return MEMPOOL_NULL_ERROR;
    }
    pNewMemPoolHead->itemAvil = itemNum;
    *ppMemPoolHead = pNewMemPoolHead;
    return MEMPOOL_SUCCESS;
}

MemPool_status newMemPool(MemPool* pMemPool, Uint16 itemSize, Int32 itemNum)
{
    if(pMemPool == NULL)
    {
        return MEMPOOL_NULL_ERROR;
    }
    if(itemSize != 0 && itemNum != 0)
    {
        MemPoolHead* pHeadPrev = &pMemPool->MemPoolHeader;
        MemPoolHead* pHeadNext = pHeadPrev->pNextHead;
        while(pHeadNext != &pMemPool->MemPoolHeader)
        {
            if(pHeadNext == NULL)
            {
                return MEMPOOL_NULL_ERROR;
            }
            if(pHeadNext->nodeSize < itemSize)
            {
                pHeadNext = pHeadNext->pNextHead;
                continue;
            }
            break;
        }
        /* 找到了合适的放置新的MemPoolHead的位置 */
        pHeadPrev = pHeadNext->pPrevHead;
        MemPoolHead* pNewMemPoolHead = NULL;
        if(MEMPOOL_SUCCESS != newMemPoolHead(&pNewMemPoolHead, pMemPool, itemSize, itemNum))
        {
            return MEMPOOL_NULL_ERROR;
        }
        pNewMemPoolHead->pPrevHead = pHeadPrev;
        pNewMemPoolHead->pNextHead = pHeadNext;
        pHeadPrev->pNextHead = pNewMemPoolHead;
        pHeadNext->pPrevHead = pNewMemPoolHead;
    }
    return MEMPOOL_SUCCESS;
}

void dumpMemPool(MemPool* pMemPool)
{
    if(pMemPool == NULL)
    {
        return;
    }
    MemPoolHead* pMemPoolHead = pMemPool->MemPoolHeader.pNextHead;
    printf("itemSize    MaxAvil    NowAvil\n");
    while(pMemPoolHead != &pMemPool->MemPoolHeader)
    {
        printf("%8d  %8d  %8d\n", pMemPoolHead->nodeSize, pMemPoolHead->maxAvil, pMemPoolHead->itemAvil);
        pMemPoolHead = pMemPoolHead->pNextHead;
    }
    return;
}

MemSpace_t memAlloc(MemPool* pMemPool, Uint16 spaceSize)
{
    if(pMemPool == NULL || spaceSize == 0)
    {
        return NULL;
    }
    MemPoolHead* pMemPoolHead = pMemPool->MemPoolHeader.pNextHead;
    /* 寻找合适的空间 */
    while(pMemPoolHead != &pMemPool->MemPoolHeader)
    {
        /* 当前空间不合适，查看下一个 */
        if((pMemPoolHead->nodeSize < spaceSize) || (pMemPoolHead->itemAvil < 1))
        {
            pMemPoolHead = pMemPoolHead->pNextHead;
            continue;
        }
        /* 找到合适的空间 */
        apr_thread_mutex_lock(pMemPoolHead->pHeadMutex);
        MemPoolNode* pMemPoolNode = pMemPoolHead->FreeMemHead.pNextNode;
        if(pMemPoolNode == &pMemPoolHead->FreeMemHead)
        {   /* 合适的空间出现问题， */
            assert(0);
            apr_thread_mutex_unlock(pMemPoolHead->pHeadMutex);
            pMemPoolHead = pMemPoolHead->pNextHead;
            continue;
        }
        if(pMemPoolNode == NULL)
        {   /* 出现非常严重的问题 */
            assert(0);
            apr_thread_mutex_unlock(pMemPoolHead->pHeadMutex);
            return NULL;
        }
        /* 找到合适的节点，从FreeHead取出，并返回 */
        pMemPoolNode->pPrevNode->pNextNode = pMemPoolNode->pNextNode;
        pMemPoolNode->pNextNode->pPrevNode = pMemPoolNode->pPrevNode;
        /* 放入usedHead */
        pMemPoolNode->pNextNode = pMemPoolHead->UsedMemHead.pNextNode;
        pMemPoolNode->pPrevNode = &pMemPoolHead->UsedMemHead;
        pMemPoolNode->pNextNode->pPrevNode = pMemPoolNode;
        pMemPoolNode->pPrevNode->pNextNode = pMemPoolNode;
/*        pMemPoolHead->UsedMemHead.pNextNode->pPrevNode = pMemPoolNode;
        pMemPoolHead->UsedMemHead.pNextNode = pMemPoolNode;*/
        pMemPoolHead->itemAvil -= 1;
        apr_thread_mutex_unlock(pMemPoolHead->pHeadMutex);
        return (char*)(pMemPoolNode + 1);
    }
    return NULL;
}

MemPool_status memFree(MemSpace_t pSpace)
{
    if(pSpace == NULL)
    {
        return MEMPOOL_NULL_ERROR;
    }
    MemPoolNode* pMemPoolNode = (MemPoolNode*)(pSpace - NODEHEADSIZE);
    MemPoolHead* pMemPoolHead = pMemPoolNode->pMemPoolHead;
    if((pMemPoolNode->check != gMemPoolCheck) || (pMemPoolHead == NULL))
    {
        return MEMPOOL_NULL_ERROR;
    }
    /*memset(pSpace, 0, pMemPoolHead->nodeSize);*/
    apr_thread_mutex_lock(pMemPoolHead->pHeadMutex);
    /* 从usehead取出 */
    pMemPoolNode->pPrevNode->pNextNode = pMemPoolNode->pNextNode;
    pMemPoolNode->pNextNode->pPrevNode = pMemPoolNode->pPrevNode;
    /* 放入FreeHead */
    pMemPoolNode->pNextNode = pMemPoolHead->FreeMemHead.pNextNode;
    pMemPoolNode->pPrevNode = &pMemPoolHead->FreeMemHead;
    pMemPoolNode->pNextNode->pPrevNode = pMemPoolNode;
    pMemPoolNode->pPrevNode->pNextNode = pMemPoolNode;
    pMemPoolHead->itemAvil += 1;
    apr_thread_mutex_unlock(pMemPoolHead->pHeadMutex);
    return MEMPOOL_SUCCESS;

}
